/*
 * @Author: intellectual-seeker 3336339701@qq.com
 * @Date: 2025-09-15 21:10:40
 * @LastEditors: intellectual-seeker 3336339701@qq.com
 * @LastEditTime: 2025-09-21 13:54:02
 * @FilePath: /code/lesson33/ThreadPool/ThreadPool.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#ifndef THREADPOOL_HPP
#define THREADPOOL_HPP
#include <vector>
#include <queue>
#include "Thread.hpp"
#include <pthread.h>
#include <iostream>
using namespace std;
using namespace ThreadModule;
#include "Log.hpp"
#include "LockGuard.hpp"

static int defaultnum = 5;

template <typename T>
class ThreadPool
{
private:
    // void Lock(pthread_mutex_t &mutex)
    void LockQueue()
    {
        pthread_mutex_lock(&_mutex);
    }

    // void Unlock(pthread_mutex_t &mutex)
    void UnlockQueue()
    {
        pthread_mutex_unlock(&_mutex);
    }

    // void WaitCond(pthread_cond_t &cond, pthread_mutex_t &mutex)
    void ThreadSleep()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }

    // void Signal(pthread_cond_t &cond)
    void ThreadWakeUp()
    {
        pthread_cond_signal(&_cond);
    }

    // void Broadcast(pthread_cond_t &cond)
    void ThreadWakeUpAll()
    {
        pthread_cond_broadcast(&_cond);
    }

private:
    ThreadPool(int threadnum = defaultnum);

    void TaskHandler(string name)
    {
        LOG(INFO, "%s running success...", name.c_str());
        while (true)
        {
            // 从缓冲区中获取任务/数据
            LockQueue();
            // 线程池正常运行，且缓冲区为空
            while (_databuff.empty() && _isrunning)
            {
                _waitnum++;
                ThreadSleep();
                _waitnum--;
            }

            // cout << name << " get queue data, is not empty, " << _databuff.empty() << endl;;

            // 线程池停止运行，且缓冲区为空，线程退出
            if (_databuff.empty() && !_isrunning)
            {
                // cout << name << " quit..." << endl;
                UnlockQueue(); // 线程退出后，释放锁
                break;
            }
            // 缓冲区不为空，获取任务执行任务
            T t;
            t = _databuff.front();
            _databuff.pop();

            UnlockQueue();
            // 执行/处理，任务/数据
            // t.DebugToStringQuestion();
            LOG(DEBUG, "%s get a task", name.c_str());

            t();

            // t.DebugToStringAnswer();
            LOG(DEBUG, "%s handler a task, result is %s", name.c_str(), t.DebugToStringAnswer().c_str());
        }
    }

    void InitThreadPool()
    {
        for (int i = 0; i < _threadnum; i++)
        {
            char name[1024];
            snprintf(name, sizeof(name), "Thread-%d", i);
            function<void(string)> func = bind(&ThreadPool::TaskHandler, this, placeholders::_1); // 成员函数要加&取地址符
            _threads.emplace_back(func, name);

            LOG(INFO, "%s create success...", name);
        }
    }

    void Start()
    {
        for (auto &thread : _threads)
        {
            thread.start();
        }
    }


    //单例模式，这个类只能有一个对象
    //只对为外GetInstance这一种方式获取对象
    //禁止拷贝构造与赋值拷贝这两个默认成员函数的自动生成，禁用
    ThreadPool(const ThreadPool<T> &) = delete;
    ThreadPool<T>& operator=(const ThreadPool<T> &) = delete;

public:
    // 可能会有多个线程同时给线程池插入数据，加锁
    // 当线程未处于运行状态时，就不能再插入新数据
    bool Enqueue(T task)
    {
        bool ret = false;
        LockQueue();
        if (_isrunning) // 可能被多个线程访问，共享资源
        {
            _databuff.push(task);
            if (_waitnum > 0)
                ThreadWakeUp();
            ret = true;
            LOG(DEBUG, "Enqueue success...");
        }
        UnlockQueue();

        return ret;
    }

    void Stop()
    {
        // 调用Stop接口
        // 修改线程池成员变量_isrunning，为什么要加锁
        LockQueue();
        _isrunning = false;
        ThreadWakeUpAll();
        UnlockQueue();
    }

    void Wait()
    {
        for (auto &thread : _threads)
        {
            thread.join();
            LOG(INFO, "%s is quit...", thread.name().c_str());
        }
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

    static ThreadPool<T> *GetInstance();

private:
    int _threadnum;
    vector<Thread> _threads;
    queue<T> _databuff;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;

    bool _isrunning;
    int _waitnum;

    static ThreadPool<T> *instance;
    static pthread_mutex_t _lock;
};

template <typename T>
ThreadPool<T> *ThreadPool<T>::instance = nullptr; // 在定义而非声明静态变量时，不能用static修饰
template <typename T>
pthread_mutex_t ThreadPool<T>::_lock = PTHREAD_MUTEX_INITIALIZER;

template <typename T>
ThreadPool<T> *ThreadPool<T>::GetInstance()
{
    if (instance == nullptr)
    {
        LockGuard loackguard(_lock);
        if (instance == nullptr)
        {
            instance = new ThreadPool();
            instance->InitThreadPool();
            instance->Start();

            LOG(DEBUG, "线程池单例创建成功");

            return instance;
        }
    }

    LOG(DEBUG, "线程池单例获取成功");

    return instance;
}

template <typename T>
ThreadPool<T>::ThreadPool(int threadnum)
    : _threadnum(threadnum), _waitnum(0)
{
    pthread_mutex_init(&_mutex, nullptr);
    pthread_cond_init(&_cond, nullptr);

    _isrunning = true;

    LOG(INFO, "ThreadPool create success...");
}

#endif